using MediatR;
using Microsoft.EntityFrameworkCore;
using WMS.Domain;
using WMS.ErrorCode;
using WMS.Infrasturcture.Interfaces;
using WMS.WebApiWrite.Application.Command;

namespace WMS.WebApiWrite.Application.Commandhandler
{
    /// <summary>
    /// 保存盘点信息命令处理器（使用事务处理盘点表、盘点明细表、上传附件表）
    /// </summary>
    public class SaveInventoryCommandHandler : IRequestHandler<SaveInventoryCommand, ApiResult<string>>
    {
        private readonly IBaseRepository<InventoryInfo> inventoryRepository;
        private readonly IBaseRepository<Inventory_check_details> detailsRepository;
        private readonly IBaseRepository<Uploadattachment> attachmentRepository;
        private static readonly Random random = new Random();

        /// <summary>
        /// 构造函数，注入三个仓储
        /// </summary>
        public SaveInventoryCommandHandler(
            IBaseRepository<InventoryInfo> inventoryRepository,
            IBaseRepository<Inventory_check_details> detailsRepository,
            IBaseRepository<Uploadattachment> attachmentRepository)
        {
            this.inventoryRepository = inventoryRepository;
            this.detailsRepository = detailsRepository;
            this.attachmentRepository = attachmentRepository;
        }

        /// <summary>
        /// 处理保存盘点信息命令
        /// </summary>
        public async Task<ApiResult<string>> Handle(SaveInventoryCommand request, CancellationToken cancellationToken)
        {
            // 使用 ExecutionStrategy 包装事务（兼容 MySQL 重试策略）
            var strategy = inventoryRepository.DB.Database.CreateExecutionStrategy();

            return await strategy.ExecuteAsync(async () =>
            {
                // 在 ExecutionStrategy 中开启事务
                using var transaction = await inventoryRepository.DB.Database.BeginTransactionAsync(cancellationToken);

                try
                {
                    var dto = request.InventoryDTO;
                    bool isEdit = dto.InventoryId.HasValue && dto.InventoryId.Value > 0;
                    string inventoryCode = string.Empty;
                    InventoryInfo inventoryInfo;

                    // ==================== 1. 处理盘点主表 ====================
                    if (isEdit)
                    {
                        // 编辑模式：查询现有记录
                        inventoryInfo = inventoryRepository.GetAll()
                            .FirstOrDefault(x => x.InventoryId == dto.InventoryId.Value && !x.IsDeleted);

                        if (inventoryInfo == null)
                        {
                            await transaction.RollbackAsync(cancellationToken);
                            return new ApiResult<string>
                            {
                                Code = ApiResultEnum.修改失败,
                                Message = "盘点信息不存在",
                                Data = null
                            };
                        }

                        // 使用现有的盘点编号
                        inventoryCode = inventoryInfo.InventoryCode;

                        // 更新盘点信息
                        inventoryInfo.WarehouseId = dto.WarehouseId;
                        inventoryInfo.HandlerrId = dto.HandlerrId;
                        inventoryInfo.InventoryDateTime = dto.InventoryDateTime;
                        inventoryInfo.InventoryEndTime = dto.InventoryEndTime;
                        inventoryInfo.InventoryContent = dto.InventoryContent;
                        inventoryInfo.InventoryQuantity = dto.InventoryQuantity;
                        inventoryInfo.SurplusQuantity = dto.SurplusQuantity;
                        inventoryInfo.InventoryShortageQuantity = dto.InventoryShortageQuantity;
                        inventoryInfo.SurplusAmount = dto.SurplusAmount;
                        inventoryInfo.InventoryLossAmount = dto.InventoryLossAmount;
                        inventoryInfo.DataStatus = dto.DataStatus;
                        inventoryInfo.UpdateName = dto.OperatorName;
                        inventoryInfo.UpdateTime = DateTime.Now;
                        inventoryInfo.InventoryTypeId= dto.InventoryTypeId;

                        await inventoryRepository.UpdateAsync(inventoryInfo);

                        // 删除旧的明细和附件（重新添加）
                        var oldDetails = detailsRepository.GetAll()
                            .Where(x => x.InventoryCode == inventoryCode)
                            .ToList();
                        if (oldDetails.Any())
                        {
                            await detailsRepository.DeleteRange(oldDetails);
                        }

                        var oldAttachments = attachmentRepository.GetAll()
                            .Where(x => x.InventoryCode == inventoryCode && !x.IsDeleted)
                            .ToList();
                        if (oldAttachments.Any())
                        {
                            await attachmentRepository.DeleteRange(oldAttachments);
                        }
                    }
                    else
                    {
                        // 新增模式：生成盘点编号
                        inventoryCode = GenerateUniqueInventoryCode();

                        // 创建盘点信息实体
                        inventoryInfo = new InventoryInfo
                        {
                            InventoryCode = inventoryCode,
                            WarehouseId = dto.WarehouseId,
                            HandlerrId = dto.HandlerrId,
                            InventoryDateTime = dto.InventoryDateTime,
                            InventoryEndTime = dto.InventoryEndTime,
                            InventoryContent = dto.InventoryContent,
                            InventoryQuantity = dto.InventoryQuantity,
                            SurplusQuantity = dto.SurplusQuantity,
                            InventoryShortageQuantity = dto.InventoryShortageQuantity,
                            SurplusAmount = dto.SurplusAmount,
                            InventoryLossAmount = dto.InventoryLossAmount,
                            IsDeleted = false,
                            DataStatus = dto.DataStatus,
                            CreateName = dto.OperatorName,
                            CreateTime = DateTime.Now,
                             InventoryTypeId= dto.InventoryTypeId
                        };

                        await inventoryRepository.AddAsync(inventoryInfo);
                    }

                    // ==================== 2. 批量添加盘点明细 ====================
                    if (dto.DetailsList != null && dto.DetailsList.Any())
                    {
                        var detailsEntities = new List<Inventory_check_details>();

                        foreach (var detailDto in dto.DetailsList)
                        {
                            var detailEntity = new Inventory_check_details
                            {
                                InventoryCode = inventoryCode, // 🎯 从后端自动赋值
                                DetailsProductName = detailDto.DetailsProductName,
                                DetailsProductCode = detailDto.DetailsProductCode,
                                SpecificationModel = detailDto.SpecificationModel,
                                DetailsUnit = detailDto.DetailsUnit,
                                book_stock = detailDto.BookStock,
                                book_amount = detailDto.BookAmount,
                                counted_stock = detailDto.CountedStock,
                                counted_stock_location = detailDto.CountedStockLocation,
                                counted_stock_raw = detailDto.CountedStockRaw,
                                counted_stock_numeric = detailDto.CountedStockNumeric,
                                profit_loss_qty = detailDto.ProfitLossQty,
                                profit_loss_amount = detailDto.ProfitLossAmount,
                                status = detailDto.Status,
                                reference_price = detailDto.ReferencePrice,
                                remark = detailDto.Remark
                            };

                            detailsEntities.Add(detailEntity);
                        }

                        await detailsRepository.AddRange(detailsEntities);
                    }

                    // ==================== 3. 批量添加上传附件 ====================
                    if (dto.AttachmentList != null && dto.AttachmentList.Any())
                    {
                        var attachmentEntities = new List<Uploadattachment>();

                        foreach (var attachmentDto in dto.AttachmentList)
                        {
                            var attachmentEntity = new Uploadattachment
                            {
                                InventoryCode = inventoryCode, // 🎯 从后端自动赋值
                                UploadUrl = attachmentDto.UploadUrl,
                                IsDeleted = false,
                                CreateName = dto.OperatorName,
                                CreateTime = DateTime.Now
                            };

                            attachmentEntities.Add(attachmentEntity);
                        }

                        await attachmentRepository.AddRange(attachmentEntities);
                    }

                    // 提交事务
                    await transaction.CommitAsync(cancellationToken);

                    // 根据不同的数据状态返回不同的成功消息
                    string message = dto.DataStatus switch
                    {
                        1 => isEdit ? "保存草稿成功" : "保存草稿成功",
                        2 => isEdit ? "修改盘点信息成功" : "新增盘点信息成功",
                        3 => isEdit ? "保存盘点信息成功" : "保存盘点信息成功",
                        _ => isEdit ? "修改成功" : "新增成功"
                    };

                    return new ApiResult<string>
                    {
                        Code = isEdit ? ApiResultEnum.修改成功 : ApiResultEnum.新增成功,
                        Message = $"{message}，盘点编号：{inventoryCode}",
                        Data = inventoryCode // 返回盘点编号
                    };
                }
                catch (Exception ex)
                {
                    // 回滚事务
                    await transaction.RollbackAsync(cancellationToken);

                    return new ApiResult<string>
                    {
                        Code = ApiResultEnum.操作失败,
                        Message = $"保存盘点信息异常：{ex.Message}",
                        Data = null
                    };
                }
            });
        }

        /// <summary>
        /// 生成唯一的盘点编号（格式：PDDH+4位随机数，如：PDDH1234）
        /// </summary>
        private string GenerateUniqueInventoryCode()
        {
            string code;
            int maxAttempts = 100;
            int attempts = 0;

            do
            {
                // 生成格式：PDDH + 4位随机数
                int randomNumber = random.Next(1000, 10000); // 4位随机数：1000-9999
                code = $"PDDH{randomNumber}"; // 例如：PDDH1234

                attempts++;
                if (attempts >= maxAttempts)
                {
                    // 如果尝试多次仍重复，使用时间戳
                    string timestamp = DateTime.Now.ToString("HHmmss");
                    code = $"PDDH{timestamp}";
                    break;
                }
            } while (inventoryRepository.GetAll().Where(x => !x.IsDeleted).Any(x => x.InventoryCode == code));

            return code;
        }
    }
}

